﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MSDN.Samples.ClaimsAuth;
using PictbaseAirApi;
using System.Data;
using System.Xml;
using System.Diagnostics;
using System.ComponentModel;
using Microsoft.SharePoint.Client;
using System.Net;
using PictbaseSharePointLibrary.SharePoint.Authentication.WS;
using Field = PictbaseAirApi.Field;

namespace PictbaseSharePointLibrary
{
    public partial class PictbaseDataSync
    {

        public void SyncPictbaseToSharePoint()
        {
            _currentStructure = EntityManager.StructureGetById(PictbaseStructureId);

            checkList();

            updateListStructure();

            checkExistingData();

            PushData();
        }

        private void checkExistingData()
        {
            XmlDocument xmlDoc = new System.Xml.XmlDocument();

            XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
            XmlNode ndViewFields =
                xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
            XmlNode ndQueryOptions =
                xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");

            ndQueryOptions.InnerXml =
                "<IncludeMandatoryColumns>FALSE</IncludeMandatoryColumns><DateInUtc>TRUE</DateInUtc>";
            ndViewFields.InnerXml = @"<FieldRef Name='ID' /><FieldRef Name='Title'/>";

            //            ndQuery.InnerXml = 
            //@"<Where><And><Gt><FieldRef Name='Field1'/>
            //<Value Type='Number'>5000</Value></Gt><Gt><FieldRef Name='Field2'/>
            //<Value Type='DateTime'>2003-07-03T00:00:00</Value></Gt></And></Where>";
            XmlNode ndListItems = null;
            try
            {
                ndListItems =
                    ListsWS.GetListItems(_list.Attributes["ID"].Value, null, ndQuery,
                    ndViewFields, null, ndQueryOptions, null);
            }

            catch (System.Web.Services.Protocols.SoapException ex)
            {
                Console.Write("Message:\n" + ex.Message + "\nDetail:\n" +
                    ex.Detail.InnerText +
                     "\nStackTrace:\n" + ex.StackTrace);
                return;
            }

            ndListItems.Normalize();

            SubmissionList slist = EntityManager.SubmissionGetList(0, int.MaxValue, _currentStructure.id, DateTime.MinValue);

            XmlNode xmlItems =
                (from x in ndListItems.ChildNodes.Cast<XmlNode>() where x.Name == "rs:data" select x).FirstOrDefault();


            foreach (Submission submission in slist)//  ndListItem in xmlItems.ChildNodes
            {
                XmlNode node = (from x in xmlItems.ChildNodes.Cast<XmlNode>()
                                where (x.Name == "z:row" && x.Attributes["ows_Title"].Value == submission.id.ToString())
                                select x).FirstOrDefault();

                if(node == null)
                {
                    submissionsToAdd.Add(submission);
                }
                else
                {
                    submissionsToUpdate.Add(Convert.ToInt32(node.Attributes["ows_ID"].Value), submission);
                }
            }

        }

        private void checkList()
        {
            var lists = ListsWS.GetListCollection();
            
            // create the list if not exists
            if ((from l in lists.ChildNodes.Cast<XmlNode>() where l.Attributes["Title"].Value == SharePointList select l).Count() == 0)
            {
                _list = ListsWS.AddList(SharePointList, "", 100);
                //_list = ListsWS.GetList(SharePointList);
            }
            else
            {
                _list = ListsWS.GetList(SharePointList);
            }
        }

        private void PushData()
        {
            /*Create an XmlDocument object and construct a Batch element and its
            attributes. Note that an empty ViewName parameter causes the method to use the default view. */
            System.Xml.XmlDocument doc = new System.Xml.XmlDocument();
            System.Xml.XmlElement batchElement = doc.CreateElement("Batch");
            batchElement.SetAttribute("OnError", "Continue");
            batchElement.SetAttribute("ListVersion", _list.Attributes["Version"].Value);
            //batchElement.SetAttribute("ViewName", "{876D8F87-8DEA-4E2A-887C-4F3E58B2DFAC}");

            /*Specify methods for the batch post using CAML. To update or delete, 
            specify the ID of the item, and to update or add, specify 
            the value to place in the specified column.*/

            

            int index = 1;
            batchElement.InnerXml = String.Concat(
                (from s in submissionsToAdd
                 select
                     String.Format(@"<Method ID='{0}' Cmd='New'>{1}</Method>",
                                   index++,
                                   String.Format("<Field Name='ID'>New</Field><Field Name='Title'>{0}</Field>", s.id) +
                                   String.Concat((from field in _structureFields
                                                  where !String.IsNullOrEmpty(field.systemName)
                                                  select
                                                      String.Format("<Field Name='{0}'>{1}</Field>", field.systemName,
                                                                    getSubmissionFieldValue(s, field.systemName))).
                                                     ToArray()))
                ).ToArray()
                ) +
                String.Concat(
                    (from s in submissionsToUpdate
                        select
                            String.Format(@"<Method ID='{0}' Cmd='Update'>{1}</Method>",
                                   index++,
                                   String.Format("<Field Name='ID'>{0}</Field><Field Name='Title'>{1}</Field>",s.Key, s.Value.id) +
                                        String.Concat((from field in _structureFields where !String.IsNullOrEmpty(field.systemName) select String.Format("<Field Name='{0}'>{1}</Field>", field.systemName, getSubmissionFieldValue(s.Value, field.systemName))).ToArray()))
                    ).ToArray());

            
            
            /*Update list items. This example uses the list GUID, which is recommended, 
            but the list display name will also work.*/
            try
            {
                var res = ListsWS.UpdateListItems(_list.Attributes["ID"].Value, batchElement);
            }
            catch (Exception ex)
            {
                Console.Write(ex.Message);
            }
        }



        private void updateListStructure()
        {
            XmlNode[] fields = (from f in _list.ChildNodes[0].ChildNodes.Cast<XmlNode>() /*where (f.Attributes["FromBaseType"] == null || f.Attributes["FromBaseType"].Value != "TRUE")*/ select f).ToArray();

            _structureFields = new List<PictbaseAirApi.Field>(_currentStructure.Fields);
            _structureFields.Add(new PictbaseAirApi.Field() { systemName = "SubmissionId" });
            _structureFields.Add(new PictbaseAirApi.Field() { systemName = "latitude" });
            _structureFields.Add(new PictbaseAirApi.Field() { systemName = "longitude" });
            _structureFields.Add(new PictbaseAirApi.Field() { systemName = "structureId" });
            _structureFields.Add(new PictbaseAirApi.Field() { systemName = "structureName" });


            List<Field> StructureNewFields = new List<PictbaseAirApi.Field>();


            foreach (Field field in _structureFields)
            {
                if ((from f in fields where (f.Attributes["StaticName"] != null && f.Attributes["StaticName"].Value == field.systemName) select f).Count() > 0)
                {
                    //OK
                }
                else
                {
                    // Mise à jour
                    StructureNewFields.Add(field);
                }
            }

            if (StructureNewFields.Count > 0)
            {
                int index = 1;
                var vv = (from field in StructureNewFields where !String.IsNullOrEmpty(field.systemName) select String.Format(@"<Method ID='{0}'>{1}</Method>", index++, GetFieldStruct(field))).ToArray();

                String strFields = string.Format("{0}",
                    String.Concat(vv));

                // Update

                XmlDocument xmlDoc = new System.Xml.XmlDocument();

                XmlNode ndDeleteFields = xmlDoc.CreateNode(XmlNodeType.Element,
                    "Fields", "");
                XmlNode ndProperties = xmlDoc.CreateNode(XmlNodeType.Element, "List",
                    "");
                //XmlAttribute ndTitleAttrib = 
                //    (XmlAttribute)xmlDoc.CreateNode(XmlNodeType.Attribute, 
                //    "Title", "");
                //XmlAttribute ndDescriptionAttrib = 
                //    (XmlAttribute)xmlDoc.CreateNode(XmlNodeType.Attribute, 
                //    "Description", "");
                XmlNode ndNewFields = xmlDoc.CreateNode(XmlNodeType.Element,
                    "Fields", "");
                XmlNode ndUpdateFields = xmlDoc.CreateNode(XmlNodeType.Element,
                    "Fields", "");

                //ndTitleAttrib.Value = "List_Name";
                //ndDescriptionAttrib.Value = "New_Description";

                //ndProperties.Attributes.Append(ndTitleAttrib);
                //ndProperties.Attributes.Append(ndDescriptionAttrib);

                ndDeleteFields.InnerXml = "";

                ndNewFields.InnerXml = strFields;

                ndUpdateFields.InnerXml = "";

                try
                {
                    XmlNode ndReturn =
                       ListsWS.UpdateList(_list.Attributes["ID"].Value,
                       null, ndNewFields, null, null,
                       _list.Attributes["Version"].Value);
                }
                catch (Exception ex)
                {
                }
            }
        }
    }
}
